package com.venutech.gongan.service.impl;

import com.baomidou.mybatisplus.plugins.Page;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.project.system.domain.SysUser;
import com.shihang.misc.date.DateTimeUtil;
import com.venutech.gongan.common.Constants;
import com.venutech.gongan.common.EquipBindingWorkType;
import com.venutech.gongan.common.InternalUserType;
import com.venutech.gongan.common.MonitorType;
import com.venutech.gongan.dao.*;
import com.venutech.gongan.dto.rpc.common.dataimport.EquipAddressExportDto;
import com.venutech.gongan.dto.rpc.common.dataimport.EquipAddressExportDto02Axes;
import com.venutech.gongan.dto.rpc.common.dataimport.EquipImportDto;
import com.venutech.gongan.entity.*;
import com.venutech.gongan.model.ResultFormat;
import com.venutech.gongan.service.QdsxjService;
import com.venutech.gongan.util.*;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;


@Service
public class QdsxjServiceImpl implements QdsxjService {

    Logger logger = LoggerFactory.getLogger(QdsxjServiceImpl.class);

    @Resource
    private QdsxjMapper qdsxjMapper;

    @Resource
    private UserTypeDataPrivilegeMapper userTypeDataPrivilegeMapper;

    @Autowired
    private OpWorkMapper opWorkMapper;

    @Autowired
    TempUserEquipPrivIegeMapper tempUserEquipPrivIegeMapper;

    @Autowired
    EquipBindingWorkMapper equipBindingWorkMapper;

    @Autowired
    EquipmenMapper equipmenMapper;

    @Autowired
    QdsxjService qdsxjService;

    @Override
    public ResultFormat insert(Qdsxj qdsxj) {

        Integer insert = qdsxjMapper.insert(qdsxj);
        if (insert > 0) {
            return ResultUtil.success();
        }else {
            return ResultUtil.error(100,"添加失败");
        }
    }

    @Override
    public int deleteById(Integer sb_id) {
        return qdsxjMapper.deleteById(sb_id);
    }

    @Override
    public Qdsxj getById(Integer sb_id) {
        Qdsxj qdsxj =  qdsxjMapper.getById(sb_id);
        if(Objects.nonNull(qdsxj) && Objects.nonNull(qdsxj.getSb_jd())) {
            qdsxj.setLongitude(NumberUtil.formatNumber(qdsxj.getSb_jd()));
        }
        if(Objects.nonNull(qdsxj) && Objects.nonNull(qdsxj.getSb_wd())) {
            qdsxj.setLatitude(NumberUtil.formatNumber(qdsxj.getSb_wd()));
        }
        return qdsxj;
    }

    @Override
    public int updateQdsxj(Qdsxj qdsxj) {
        return qdsxjMapper.updateQdsxj(qdsxj);
    }

    //分页数据查询
    @Override
    public Page<Qdsxj> getInfo(Integer pageNo, Integer pageSize, String begintime, String endtime, String badw, String sb_name,String sb_type,String sb_state, SysUser user) {
        Page<Qdsxj> page = new Page<>(pageNo,pageSize);
        List<Qdsxj> list = new ArrayList<>();
        PageUtils.startPage();
        InternalUserType internalUserType = InternalUserType.getUserTypeByValue(user.getGonganUserType());
        if(internalUserType == InternalUserType.ADMIN_USER || internalUserType == InternalUserType.RESERVED_USER) {
            list = qdsxjMapper.getInfo(begintime,endtime,badw,page,sb_name,sb_type,sb_state);
        } else if (internalUserType == InternalUserType.POLICE_USER) {
//            UserTypeDataPrivilege userTypeDataPrivilege = userTypeDataPrivilegeMapper.getByUserTypeAndResourceCode(user.getUser_type(), Constants.RESOURCE_CODE_QDSXJ);
//            if(Objects.nonNull(userTypeDataPrivilege) &&userTypeDataPrivilege.getResource_field_code().equals(Constants.RESOURCE_FIELD_CODE_XZQY)) {
//                list = qdsxjMapper.getInfoWithDataPrivilege(begintime,endtime,badw,page,sb_name, Constants.RESOURCE_FIELD_CODE_XZQY, user.getUser_area());
//            }
            list = qdsxjMapper.getInfo(begintime,endtime,badw,page,sb_name,sb_type,sb_state);
        }
        page.setTotal(new PageInfo<>(list).getTotal());
        return page.setRecords(list);
    }

    @Override
    public List<Qdsxj> getEquipmentList(Double gw_jd, Double gw_wd,Double radius) {
        return qdsxjMapper.getEquipmentList(gw_jd,gw_wd,radius);
    }

    @Override
    public List<Qdsxj> getEquipmentListForMonitorType(Double gw_jd, Double gw_wd,Double radius) {
        return qdsxjMapper.getEquipmentListForMonitorType(gw_jd,gw_wd,radius);
    }

    //API
    @Override
    public Qdsxj getBySbBm(String sb_bm) {
        return qdsxjMapper.getBySbBm(sb_bm);
    }

    @Override
    public String getEquipmentState(Integer equipmentId) {
        return qdsxjMapper.getEquipmentState(equipmentId);
    }

    @Override
    public int getSbCount() {
        return qdsxjMapper.getSbCount();
    }

    @Override
    public int getBoundSbCount() {
        return qdsxjMapper.getBoundSbCount();
    }

    /**
     * 获取绑定表里面所有绑定的sb_id和设备sb_id
     * @return
     */
    @Override
    public List<Qdsxj> getCameraInEquipmenteList(Map<String,Object> map) {
        System.err.println(map);
        String gw_jd = String.valueOf(map.get("longitude"));//经度
        String gw_wd = String.valueOf(map.get("latitude"));//纬 度
        Double radius =Double.valueOf(map.get("radius").toString());//半径
        return qdsxjMapper.getCameraInEquipmenteList(gw_jd,gw_wd,radius);
    }

    @Override
    public List<Qdsxj> getCameraInEquipmenteListForMonitorType(Map<String,Object> map) {
        System.err.println(map);
        String gw_jd = String.valueOf(map.get("longitude"));//经度
        String gw_wd = String.valueOf(map.get("latitude"));//纬 度
        Double radius =Double.valueOf(map.get("radius").toString());//半径
        return qdsxjMapper.getCameraInEquipmenteListForMonitorType(gw_jd,gw_wd,radius);
    }

    @Override
    public void batchImport(List<EquipImportDto> equipImportList) {

        AtomicInteger rowNum = new AtomicInteger(0);
        AtomicInteger failNum = new AtomicInteger(0);
        logger.warn("begin equip info batch import: {} records. ", equipImportList.size());

        for(int i=0; i< equipImportList.size(); i++) {
            rowNum.getAndIncrement();
            EquipImportDto equip = equipImportList.get(i);
//            if(!equip.getAreaCode().contains("320508")) {
//                logger.warn("import equip area code not belongs to 320508(姑苏), [{}]", equip.getAreaCode());
//            }
            if(Strings.isBlank(equip.getEquipGbid())) {
                logger.warn("import equip gbid is null, rowNum = {}, equipName={}, areaCode={}", rowNum.get(), equip.getEquipName(), equip.getAreaCode());
                failNum.getAndIncrement();
                continue;
            }
            Qdsxj qdsxj = qdsxjMapper.getBySbBm(equip.getEquipGbid());
            if(Objects.nonNull(qdsxj)) {
                logger.warn("import equip gbid already exists, rowNum = {}, gbid={}, newEquipName={}, newAreaCode={}, newLogitude={}, newLatitude={}, " +
                        "existedEquipName={}, existedAreaCode={}, existedLogitude={}, existedLatitude={}",
                        rowNum.get(), equip.getEquipGbid(), equip.getEquipName(), equip.getAreaCode(), equip.getLogitude(), equip.getLatitude(),
                        qdsxj.getSb_name(), qdsxj.getSb_xzqy(), qdsxj.getSb_jd(), qdsxj.getSb_wd());
                failNum.getAndIncrement();
                continue;
            }

            try {
                Qdsxj newQdsxj = insertAssamble(equip);
                logger.info("import row : {} of {}, gbid = {}, equipName = {}", rowNum.get(), equipImportList.size(), newQdsxj.getSb_bm(), newQdsxj.getSb_name());
                qdsxjMapper.insert(newQdsxj);

            } catch(Exception ex) {
                logger.warn("import equip got exception. rowNum = {}, equipName={}, areaCode={}, ex=", rowNum.get(), equip.getEquipName(), equip.getAreaCode(), ex);
                failNum.getAndIncrement();
                continue;
            }
        }

        logger.warn("batch import equip ends, total:{}, failNum: {}. ", equipImportList.size(), failNum.get());

    }

    @Override
    public void batchSupplyImport(List<EquipImportDto> equipImportList) {
        AtomicInteger rowNum = new AtomicInteger(0);
        AtomicInteger failNum = new AtomicInteger(0);
        AtomicInteger updateNum = new AtomicInteger(0);
        AtomicInteger newInsertNum = new AtomicInteger(0);

        // Step-1: 循环更新、新增设备信息
        logger.info("batchSupplyImport: begin equip info batch supply import, step-1: data merge: {} records. ", equipImportList.size());
        for(int i=0; i< equipImportList.size(); i++) {
            rowNum.getAndIncrement();
            EquipImportDto equip = equipImportList.get(i);
            if (Strings.isBlank(equip.getEquipGbid())) {
                logger.warn("import equip gbid is null, rowNum = {}, equipName={}, areaCode={}", rowNum.get(), equip.getEquipName(), equip.getAreaCode());
                failNum.getAndIncrement();
                continue;
            }
            try {
                Qdsxj qdsxj = qdsxjMapper.getBySbBm(equip.getEquipGbid());
                if (Objects.nonNull(qdsxj)) {   // 设备信息已存在于数据库, 更新
                    logger.info("batchSupplyImport: begin to update equip, rowNum = {}, gbid={}, newEquipName={}, newAreaCode={}, newLogitude={}, newLatitude={}, " +
                                    "existedEquipName={}, existedAreaCode={}, existedLogitude={}, existedLatitude={}",
                            rowNum.get(), equip.getEquipGbid(), equip.getEquipName(), equip.getAreaCode(), equip.getLogitude(), equip.getLatitude(),
                            qdsxj.getSb_name(), qdsxj.getSb_xzqy(), qdsxj.getCorrect_longitude(), qdsxj.getCorrect_latitude());
                    qdsxj = updateAssamble(equip, qdsxj);
                    assambleAccuratePosition(qdsxj);
                    qdsxjMapper.updateQdsxj2(qdsxj);
                    updateNum.getAndIncrement();
                    logger.info("batchSupplyImport: update equip row : {} of {}, updateNum = {},  [sb_id = {}, gbid = {}, sb_name = {}] ", rowNum.get(), equipImportList.size(), updateNum.get(), qdsxj.getSb_id(), qdsxj.getSb_bm(), qdsxj.getSb_name());
                } else {
                    logger.info("batchSupplyImport: begin to insert equip, rowNum = {}, gbid={}, newEquipName={}, newAreaCode={}, newLogitude={}, newLatitude={}",
                            rowNum.get(), equip.getEquipGbid(), equip.getEquipName(), equip.getAreaCode(), equip.getLogitude(), equip.getLatitude());
                    Qdsxj newQdsxj = insertAssamble(equip);
                    assambleAccuratePosition(newQdsxj);
                    qdsxjMapper.insert(newQdsxj);
                    newInsertNum.getAndIncrement();
                    logger.info("batchSupplyImport: import equip row : {} of {}, newInsertNum = {}, [gbid = {}, sb_name = {}]", rowNum.get(), equipImportList.size(), newInsertNum.get(), newQdsxj.getSb_bm(), newQdsxj.getSb_name());
                }
            } catch(Exception ex1) {
                logger.warn("import equip step-1 got exception. rowNum = {}, equipGbid={}, equipName={}, areaCode={}, ex=", rowNum.get(), equip.getEquipGbid(), equip.getEquipName(), equip.getAreaCode(), ex1);
                failNum.getAndIncrement();
                continue;
            }
        }
        logger.warn("batchSupplyImport batch supply import equip step-1 ends, total:{}, updateNum: {} , newInsertNum={}, failNum={}. ", equipImportList.size(), updateNum.get(), newInsertNum.get(), failNum.get());


        // Step-2: 循环更新非停用设备中、有相同设备名的老设备的绑定关系
        rowNum.set(0);
        AtomicInteger unBoundNum = new AtomicInteger(0);
        AtomicInteger newBoundNum = new AtomicInteger(0);
        List<EquipImportDto> nonStopEquipList = equipImportList.stream().filter(eq ->
                eq.getEquipState().equals(String.valueOf(Constants.EQUIP_STATUS_NORMAL)) || eq.getEquipState().equals(String.valueOf(Constants.EQUIP_STATUS_MAINTAIN))).collect(Collectors.toList());
        List<EquipImportDto> stopEquipList = equipImportList.stream().filter(eq ->
                eq.getEquipState().equals(String.valueOf(Constants.EQUIP_STATUS_STOP))).collect(Collectors.toList());

        logger.warn("batchSupplyImport: begin equip info batch supply import, step-2: equip bound info update (equipmen): {} records. ", nonStopEquipList.size());
        for(int i=0; i< nonStopEquipList.size(); i++) {
            // 查询是否有相同名称的设备已存在，当做被替换的设备
            rowNum.getAndIncrement();
            EquipImportDto equip = nonStopEquipList.get(i);
            List<Qdsxj> sameNameEquips = qdsxjMapper.getByEquipName(equip.getEquipName());
            sameNameEquips = sameNameEquips.stream().filter(eq -> !eq.getSb_bm().equals(equip.getEquipGbid())).collect(Collectors.toList());
            if(CollectionUtils.isEmpty(sameNameEquips)) {
                continue;
            }
            try {
                // 有相同名称的设备存在，且在状态停用列表中，看做被替换的设备
                boolean hasBoundedRelation = false;
                Equipmen boundedEquipmen = null;
                for (Qdsxj sameNameEquip : sameNameEquips) {
                    boolean existsInStopList = stopEquipList.stream().anyMatch(eq -> eq.getEquipGbid().equals(sameNameEquip.getSb_bm()));
                    if (!existsInStopList) {
                        continue;
                    }
                    List<Equipmen> equipmens = equipmenMapper.getBySbid(sameNameEquip.getSb_id());
                    if (CollectionUtils.isEmpty(equipmens)) {
                        continue;
                    }
                    hasBoundedRelation = true;
                    boundedEquipmen = equipmens.get(0);
                    equipmenMapper.unBindPoleid(boundedEquipmen.getGw_id(), boundedEquipmen.getSb_id());  // 旧设备解绑
                    unBoundNum.getAndIncrement();
                }
                // 如果有被替换设备已在设备绑定表中存在，则将新的设备的id也绑定进去
                if (hasBoundedRelation) {
                    Qdsxj qdsxj = qdsxjMapper.getBySbBm(equip.getEquipGbid());
                    equipmenMapper.insertSbBind(boundedEquipmen.getQr_id(), boundedEquipmen.getGw_id(), qdsxj.getSb_id());
                    newBoundNum.getAndIncrement();
                    logger.warn("batchSupplyImport: 替换设备新增绑定关系: row {} of {}, qr_id={}, gw_id={}, sb_id={}", rowNum.get(), nonStopEquipList.size(), boundedEquipmen.getQr_id(), boundedEquipmen.getGw_id(), qdsxj.getSb_id());
                }
            }catch(Exception ex2) {
                logger.warn("import equip step-2 got exception. rowNum = {}, equipSbId = {}, equipName={}, areaCode={}, ex=", rowNum.get(), equip.getEquipGbid(), equip.getEquipName(), equip.getAreaCode(), ex2);
                failNum.getAndIncrement();
                continue;
            }
        }
        logger.warn("batchSupplyImport batch supply import equip step-2 ends， total:{}, newBoundNum(equipmen)= {}, unboundNum={}. failNum = {}", nonStopEquipList.size(), newBoundNum.get(), unBoundNum.get(), failNum.get());

    }

    /**
     * 批量更新设备区域监控类型
     * @param equipImportList
     */
    @Override
    public void batchUpdateMonitorType(List<EquipImportDto> equipImportList) {
        AtomicInteger rowNum = new AtomicInteger(0);
        AtomicInteger failNum = new AtomicInteger(0);
        logger.warn("begin equip info batch update monitor type: {} records. ", equipImportList.size());

        for(int i=0; i< equipImportList.size(); i++) {
            rowNum.getAndIncrement();
            EquipImportDto equip = equipImportList.get(i);
            Qdsxj qdsxj = qdsxjMapper.getBySbBm2(equip.getEquipGbid());
            if(Objects.nonNull(qdsxj)) {
                logger.warn("update equip monitor type: rowNum = {}, gbid={}, equipName={}, areaCode={}, monitorType={} ",
                        rowNum.get(), equip.getEquipGbid(), equip.getEquipName(), equip.getAreaCode(), equip.getMonitorAreaType());
                if(Strings.isNotBlank(equip.getMonitorAreaType())) {
                    try {
                        int monitorType = Integer.valueOf(equip.getMonitorAreaType());
                        qdsxjMapper.updateQdsxjMonitorType(qdsxj.getSb_id(), monitorType);
                    } catch(Exception e) {
                        logger.error("update equip monitor type error: rowNum = {}, gbid={}, equipName={}, areaCode={} ",
                                rowNum.get(), equip.getEquipGbid(), equip.getEquipName(), equip.getAreaCode(), e);
                    }
                }

            }
        }

    }

    @Override
    public List<Qdsxj> getAll() {
        return qdsxjMapper.getAllEquipments();
    }

    @Override
    public int updateCorrectLongitudeAndLatitude(int sbId, double correctLongitude, double correctLatitude) {
        return qdsxjMapper.updateQdsxjCorrectLongitudeAndLatitude(sbId, correctLongitude, correctLatitude);
    }

    @Override
    public int updateAccurateAddress(int sbId, String accurateAddress, String accurateTownCode, String accurateTownName) {
        return qdsxjMapper.updateQdsxjAccurateAddress(sbId, accurateAddress, accurateTownCode, accurateTownName);
    }

    /**
     * @Author liuzhengli
     * @Description //TODO  获取所有设备
     * @Date  2021/8/10 0010 10:29
     * @Param * @param null:
     * @return
     */
    @Override
    public List<Qdsxj> getQdsxjList() {
        return qdsxjMapper.getQdsxjList();
    }

    /**
     * @Author liuzhengli
     * @Description //TODO 根据当前指定的半径获取所有设备
     * @Date  2021/8/10 0010 10:41
     * @Param * @param null:
     * @return
     */
    @Override
    public List<Qdsxj> getQdsxjListBylatandlog(Double gw_jd, Double gw_wd, Double radius) {
               return qdsxjMapper.getQdsxjListBylatandlog(gw_jd, gw_wd, radius);
    }

    @Override
    public List<String> getSubAreaCodeList(String areaCode) {
        return qdsxjMapper.getSubAreaCodeByAreaCode(areaCode);
    }

//    @Override
//    public List<EquipAddressExportDto> getEquipmentListBySubAreaCode(String subAreaCode, String subAreaName) {
//        List<EquipAddressExportDto> exportDtos = new ArrayList<>();
//        List<Qdsxj> qdsxjList =  qdsxjMapper.getEquipmentListBySubAreaCode(subAreaCode);
//        if(CollectionUtils.isEmpty(qdsxjList)) {
//            return exportDtos;
//        }
//        qdsxjList.forEach(qdsxj -> {
//            EquipAddressExportDto dto = new EquipAddressExportDto();
//            dto.setEquipId(qdsxj.getSb_id());
//            dto.setEquipName(qdsxj.getSb_name());
//            dto.setDetailAddress(qdsxj.getSb_azdz());
//            dto.setPreferenceAddress(qdsxj.getAccurate_address());
//            dto.setLongitude(qdsxj.getSb_jd());
//            dto.setLatitude(qdsxj.getSb_wd());
//            dto.setSubAreaCode(subAreaCode+subAreaName);
//            exportDtos.add(dto);
//        });
//        return exportDtos;
//    }

    @Override
    public List<String> getTownCodeList(String areaCode) {
        return qdsxjMapper.getTownCodeByAreaCode(areaCode);
    }

    @Override
    public List<EquipAddressExportDto> getEquipmentListByTownCode(String townCode) {
        List<EquipAddressExportDto> exportDtos = new ArrayList<>();
        List<Qdsxj> qdsxjList =  qdsxjMapper.getEquipmentListByTownCode(townCode);
        if(CollectionUtils.isEmpty(qdsxjList)) {
            return exportDtos;
        }
        qdsxjList.forEach(qdsxj -> {
            EquipAddressExportDto dto = new EquipAddressExportDto();
            dto.setEquipId(qdsxj.getSb_id());
            dto.setEquipName(qdsxj.getSb_name());
            dto.setDetailAddress(qdsxj.getSb_azdz());
            dto.setPreferenceAddress(qdsxj.getAccurate_address());
            dto.setLongitude(qdsxj.getSb_jd());
            dto.setLatitude(qdsxj.getSb_wd());
            dto.setTownArea(qdsxj.getAccurate_towncode() + qdsxj.getAccurate_townname());
            dto.setSubAreaCode(qdsxj.getSb_xzqy());
            exportDtos.add(dto);
        });
        return exportDtos;
    }

    @Override
    public List<EquipAddressExportDto02Axes> getEquipmentListByTownCode2(String townCode) {
        List<EquipAddressExportDto02Axes> exportDtos = new ArrayList<>();
        List<Qdsxj> qdsxjList =  qdsxjMapper.getEquipmentListByTownCode(townCode);
        if(CollectionUtils.isEmpty(qdsxjList)) {
            return exportDtos;
        }
        qdsxjList.forEach(qdsxj -> {
            EquipAddressExportDto02Axes dto = new EquipAddressExportDto02Axes();
            dto.setEquipName(qdsxj.getSb_name());
            dto.setPreferenceAddress(qdsxj.getAccurate_address());
            try {
                double[] wgs02 = GpsCoordinateUtils.calWGS84toGCJ02(qdsxj.getSb_wd(), qdsxj.getSb_jd());
                dto.setLongitude02Axes(wgs02[1]);
                dto.setLatitude02Axes(wgs02[0]);
            } catch(Exception ex) {
                logger.warn("getEquipmentListByTownCode2: 获取02坐标系经纬度异常", ex);
                dto.setLongitude02Axes(0);
                dto.setLatitude02Axes(0);
            }
            dto.setSubAreaCode(qdsxj.getSb_xzqy());
            dto.setTownArea(qdsxj.getAccurate_towncode() + qdsxj.getAccurate_townname());
            exportDtos.add(dto);
        });
        return exportDtos;
    }

    @Override
    public List<EquipAddressExportDto> getEquipmentListByMonitorTypeAndUserType(int monitorType, TempUser tempUser) {
        List<EquipAddressExportDto> exportDtos = new ArrayList<>();
        List<Qdsxj> equipments = qdsxjMapper.getNotBindedEquipmentListByMonitorType(MonitorType.FIRST_CLASS.getValue());
        if(CollectionUtils.isEmpty(equipments)) {
            return exportDtos;
        }

        List<Qdsxj> filteredEquipments = equipments;
        if(tempUser.getUser_type() == Constants.TEMP_USER_TYPE_WORKER) {
            TempUserEquipPrivIege tempPriv = tempUserEquipPrivIegeMapper.getAreaByTempUserId(tempUser.getTmp_user_id());
            filteredEquipments = equipments.stream().filter(eq -> regionUtil.isInRectangleArea(eq.getSb_wd(), eq.getSb_jd(), tempPriv.getLeft_top_latitude(), tempPriv.getLeft_top_longitude(), tempPriv.getRight_bottom_latitude(), tempPriv.getRight_bottom_longitude()))
                    .collect(Collectors.toList());
        }
        filteredEquipments.forEach(qdsxj -> {
            EquipAddressExportDto dto = new EquipAddressExportDto();
            dto.setEquipId(qdsxj.getSb_id());
            dto.setEquipName(qdsxj.getSb_name());
            dto.setDetailAddress(qdsxj.getSb_azdz());
            dto.setPreferenceAddress(qdsxj.getAccurate_address());
            dto.setLongitude(qdsxj.getSb_jd());
            dto.setLatitude(qdsxj.getSb_wd());
            dto.setTownArea(qdsxj.getAccurate_townname());
            dto.setSubAreaCode(qdsxj.getSb_xzqy());
            exportDtos.add(dto);
        });

        exportDtos.sort(Comparator.comparing(EquipAddressExportDto::getTownArea));
        return exportDtos;

    }

    @Override
    @Transactional
    public void correctPosition(int equipBindWorkId, int poleId, double longitude, double latitude, List<Integer> equipIds) {
        EquipBindingWork equipBindingWork = equipBindingWorkMapper.getById(equipBindWorkId);
        for(Integer equipId : equipIds) {
            qdsxjMapper.correctLongitudeAndLatitude(equipId, longitude, latitude);
            logger.info("correctPosition: equipBindWorkId={}, poleId={}, equipId={}, longitude={}, latitude={}", equipBindWorkId, equipBindingWork.getPole_id(), equipId, longitude, latitude);
        }
        equipBindingWorkMapper.updateEquipBindWorkStatusByPoleIdAndType(poleId, EquipBindingWorkType.PositionInCorrect.getValue(), Constants.EQUIP_BINDING_WORK_STATE_HANDLED);
        logger.info("correctPosition: update equip bindig work status to be handled. equipId={}", equipBindWorkId);
    }

    /**
     *获取当天前端设备
     * @param
     * @return
     */
    @Override
    public List<Qdsxj> getQeviceAll(String dateString) {
        return qdsxjMapper.getQeviceAll(dateString);
    }

    /**
     * 根据日期来获取前端设备
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public List<Qdsxj> getQeviceDayByStartTimeAndEndTime(String startTime, String endTime) {
        return qdsxjMapper.getQeviceDayByStartTimeAndEndTime(startTime,endTime);
    }

    private Qdsxj insertAssamble(EquipImportDto equipImportDto) {
        Qdsxj qdsxj = new Qdsxj();
        qdsxj.setSb_bm(equipImportDto.getEquipGbid());
        qdsxj.setSb_name(equipImportDto.getEquipName());
        qdsxj.setSb_dwname(equipImportDto.getPointName());
        qdsxj.setSb_factroy(equipImportDto.getFactoryName());
        qdsxj.setSb_xh(equipImportDto.getEquipTypeName());
        qdsxj.setSb_xzqy(equipImportDto.getAreaCode());
        qdsxj.setSb_azdz(equipImportDto.getAddressDetail());
        qdsxj.setSb_jd(Double.valueOf(equipImportDto.getLogitude()));
        qdsxj.setSb_wd(Double.valueOf(equipImportDto.getLatitude()));
        qdsxj.setSb_ipv4(equipImportDto.getIpv4());
        qdsxj.setSb_ipv6(equipImportDto.getIpv6());
        qdsxj.setSb_devicePtzType(equipImportDto.getCameraType());
        qdsxj.setSb_gntype(equipImportDto.getEquipFunctionType());
        qdsxj.setSb_wztype(equipImportDto.getCameraLocationType());
        qdsxj.setSb_bg(equipImportDto.getCameraLightFill());
        qdsxj.setSb_fw(equipImportDto.getDirection());
        qdsxj.setSb_fbl(equipImportDto.getResolutionRatio());
        qdsxj.setSb_code(equipImportDto.getCameraCodec());
        qdsxj.setSb_lw(equipImportDto.getNetworkingProperty());
        qdsxj.setSb_ssjg(equipImportDto.getPoliceUnitCode());
        qdsxj.setSb_ssbm(equipImportDto.getDepartmentOrTrade());
        qdsxj.setSb_bcsj(equipImportDto.getVideoTtl());
        if(Strings.isNotBlank(equipImportDto.getInstallationTime())) {
            try {
                String installTime = DateTimeUtil.formatTimestamp(Long.valueOf(equipImportDto.getInstallationTime()), "yyyy-MM-dd HH:mm:ss");
                qdsxj.setSb_azsj(DateTimeUtil.formatDate(installTime, "yyyy-MM-dd HH:mm:ss"));
            } catch (Exception ex) {
                logger.warn("date format failed. equipImportDto.InstallationTime = {}", equipImportDto.getInstallationTime());
            }
        }
        qdsxj.setSb_jsgd(equipImportDto.getHeight());
        qdsxj.setSb_gldw(equipImportDto.getMaintaincePoliceUnit());
        qdsxj.setSb_gldwtel(equipImportDto.getMaintaincePoliceUnitContact());
        qdsxj.setSb_state(equipImportDto.getEquipState());
        if(Strings.isNotBlank(equipImportDto.getPositionUpdateTime())) {
            try {
                String updateTime = DateTimeUtil.formatTimestamp(Long.valueOf(equipImportDto.getPositionUpdateTime()), "yyyy-MM-dd HH:mm:ss");
                qdsxj.setSb_gxsj(DateTimeUtil.formatDate(updateTime, "yyyy-MM-dd HH:mm:ss"));
            } catch (Exception ex) {
                logger.warn("date format failed. equipImportDto.PositionUpdateTime = {}", equipImportDto.getPositionUpdateTime());
            }
        }
        qdsxj.setSb_dk(equipImportDto.getPort());
        qdsxj.setSb_ywdw(equipImportDto.getMaintainenceCompany());
        qdsxj.setSb_glsb(equipImportDto.getRelatedEquip());
        qdsxj.setSb_ccip(equipImportDto.getStorageIp());
        qdsxj.setSb_sstype(equipImportDto.getEquipType());
        qdsxj.setCorrect_longitude(qdsxj.getSb_jd());
        qdsxj.setCorrect_latitude(qdsxj.getSb_wd());
        qdsxj.setMonitor_type(Integer.valueOf(equipImportDto.getMonitorAreaType()));
        qdsxj.setSb_type(equipImportDto.getEquipCategory());
        return qdsxj;
    }

    private Qdsxj updateAssamble(EquipImportDto equipImportDto, Qdsxj qdsxj) {
        qdsxj.setSb_name(equipImportDto.getEquipName());
        qdsxj.setSb_dwname(equipImportDto.getPointName());
        qdsxj.setSb_factroy(equipImportDto.getFactoryName());
        qdsxj.setSb_xh(equipImportDto.getEquipTypeName());
        qdsxj.setSb_xzqy(equipImportDto.getAreaCode());
        qdsxj.setSb_azdz(equipImportDto.getAddressDetail());
        qdsxj.setSb_ipv4(equipImportDto.getIpv4());
        qdsxj.setSb_ipv6(equipImportDto.getIpv6());
        qdsxj.setSb_devicePtzType(equipImportDto.getCameraType());
        qdsxj.setSb_gntype(equipImportDto.getEquipFunctionType());
        qdsxj.setSb_wztype(equipImportDto.getCameraLocationType());
        qdsxj.setSb_bg(equipImportDto.getCameraLightFill());
        qdsxj.setSb_fw(equipImportDto.getDirection());
        qdsxj.setSb_fbl(equipImportDto.getResolutionRatio());
        qdsxj.setSb_code(equipImportDto.getCameraCodec());
        qdsxj.setSb_lw(equipImportDto.getNetworkingProperty());
        qdsxj.setSb_ssjg(equipImportDto.getPoliceUnitCode());
        qdsxj.setSb_ssbm(equipImportDto.getDepartmentOrTrade());
        qdsxj.setSb_bcsj(equipImportDto.getVideoTtl());
        if (Strings.isNotBlank(equipImportDto.getInstallationTime())) {
            try {
                String installTime = DateTimeUtil.formatTimestamp(Long.valueOf(equipImportDto.getInstallationTime()), "yyyy-MM-dd HH:mm:ss");
                qdsxj.setSb_azsj(DateTimeUtil.formatDate(installTime, "yyyy-MM-dd HH:mm:ss"));
            } catch (Exception ex) {
                logger.warn("date format failed. equipImportDto.InstallationTime = {}", equipImportDto.getInstallationTime());
            }
        }
        qdsxj.setSb_jsgd(equipImportDto.getHeight());
        qdsxj.setSb_gldw(equipImportDto.getMaintaincePoliceUnit());
        qdsxj.setSb_gldwtel(equipImportDto.getMaintaincePoliceUnitContact());
        qdsxj.setSb_state(equipImportDto.getEquipState());
        if (Strings.isNotBlank(equipImportDto.getPositionUpdateTime())) {
            try {
                String updateTime = DateTimeUtil.formatTimestamp(Long.valueOf(equipImportDto.getPositionUpdateTime()), "yyyy-MM-dd HH:mm:ss");
                qdsxj.setSb_gxsj(DateTimeUtil.formatDate(updateTime, "yyyy-MM-dd HH:mm:ss"));
            } catch (Exception ex) {
                logger.warn("date format failed. equipImportDto.PositionUpdateTime = {}", equipImportDto.getPositionUpdateTime());
            }
        }
        qdsxj.setSb_dk(equipImportDto.getPort());
        qdsxj.setSb_ywdw(equipImportDto.getMaintainenceCompany());
        qdsxj.setSb_glsb(equipImportDto.getRelatedEquip());
        qdsxj.setSb_ccip(equipImportDto.getStorageIp());
        qdsxj.setSb_sstype(equipImportDto.getEquipType());
        qdsxj.setCorrect_longitude(Double.valueOf(equipImportDto.getLogitude()));
        qdsxj.setCorrect_latitude(Double.valueOf(equipImportDto.getLatitude()));
        qdsxj.setMonitor_type(Integer.valueOf(equipImportDto.getMonitorAreaType()));
        qdsxj.setSb_type(equipImportDto.getEquipCategory());
        return qdsxj;

    }

    /**
     * 设置参考街道地址和街道编码
     * @param qdsxj
     * @return
     */
    private Qdsxj assambleAccuratePosition(Qdsxj qdsxj) {
        String accurateAddress = "";
        String accurateTownCode = "";
        String accurateTownName = "";
        double[] wgs02 = GpsCoordinateUtils.calWGS84toGCJ02(qdsxj.getCorrect_latitude(), qdsxj.getCorrect_longitude());
        if(Objects.nonNull(wgs02)) {
            Address address = null;
            try {
                address = AddressUtils.getAddressByHttp(wgs02[1], wgs02[0]);
            }catch(Exception ex) {
                logger.error("assambleAccuratePosition: 获取参考街道异常， sb_id ={}, sb_name={},  wgs02={}，  ex = ", qdsxj.getSb_id(), qdsxj.getSb_name(), wgs02, ex);
            }
            if(Objects.nonNull(address)) {
                accurateAddress = address.getAddress();
                if(org.apache.commons.lang3.StringUtils.isNotBlank(address.getStreetAndNumber())) {
                    accurateAddress += "-" + address.getStreetAndNumber();
                }
                if(org.apache.commons.lang3.StringUtils.isNotBlank(address.getBuilding())) {
                    accurateAddress += "-" + address.getBuilding();
                }
                if(org.apache.commons.lang3.StringUtils.isNotBlank(address.getTownCode())) {
                    accurateTownCode = address.getTownCode();
                }
                if(org.apache.commons.lang3.StringUtils.isNotBlank(address.getTownName())) {
                    accurateTownName = address.getTownName();
                }
                qdsxj.setAccurate_address(accurateAddress);
                qdsxj.setAccurate_towncode(accurateTownCode);
                qdsxj.setAccurate_townname(accurateTownName);
            }
        }
        return qdsxj;
    }

    @Override
    public void updateDeviceIdAndDomainId(Integer sb_id, String deviceId, String domainId) {
         qdsxjMapper.updateDeviceIdAndDomainId(sb_id, deviceId, domainId);
    }

    @Override
    public Qdsxj getDeviceIdByGbid(String gbid) {
        return qdsxjMapper.getDeviceIdByGbid(gbid);
    }

    @Override
    public List<Qdsxj> getQeviceByDay(String starttime,String sb_name) {
               return qdsxjMapper.getQeviceByDay(starttime,sb_name);
    }

    /**
     * 根据日期来获取前端设备 根据gbid获取识别device_id和domain_id
     * @param gbid
     * @param deviceId
     *  @param domainId
     * @return
     */
    @Override
    public int updateDeviceAndDomain(String gbid, String deviceId, String domainId) {
        return qdsxjMapper.updateDeviceAndDomain(gbid,deviceId,domainId);
    }

    @Override
    public List<Qdsxj> getQdsxjBySbNameAndTypeList(String sb_name,String sb_type,String sb_ywdw) {
        List<Qdsxj> list_qdsxj =null;
        List<Equipmen> equipmen_list =null;

        list_qdsxj=ConcurrentHashMapUntil.getCache("cacheMap_2021");
        equipmen_list=ConcurrentHashMapUntil.getEquipmenCache("cacheEquiMap_2021");
        if(CollectionUtils.isEmpty(list_qdsxj) || CollectionUtils.isEmpty(equipmen_list)){
            list_qdsxj = qdsxjMapper.getQdsxjBySbNameList();
            equipmen_list = equipmenMapper.getEquList();
            if(!CollectionUtils.isEmpty(list_qdsxj) || !CollectionUtils.isEmpty(equipmen_list)){
                ConcurrentHashMapUntil.initDeviceCache("cacheMap_2021",list_qdsxj);
                ConcurrentHashMapUntil.initDeviceCache("cacheEquiMap_2021",equipmen_list);

                ConcurrentHashMapUntil.initDeviceSizeCache("cacheMap_2021",list_qdsxj.size());
                ConcurrentHashMapUntil.initDeviceSizeCache("cacheEquiMap_2021",equipmen_list.size());
            }
        }
       //

        int cachMapSize=ConcurrentHashMapUntil.getDeviceSizeCache("cacheMap_2021");
        int cachEquiSize=ConcurrentHashMapUntil.getDeviceSizeCache("cacheEquiMap_2021");
        if(cachMapSize>list_qdsxj.size()){
            List devicelist = qdsxjMapper.getQdsxjBySbNameList();
            ConcurrentHashMapUntil.removeCache("cacheMap_2021");
            ConcurrentHashMapUntil.initDeviceCache("cacheMap_2021",list_qdsxj);
            ConcurrentHashMapUntil.initDeviceSizeCache("cacheMap_2021",devicelist.size());
        }
        if(cachEquiSize>equipmen_list.size()){
            List equipmenlist = equipmenMapper.getEquList();
            ConcurrentHashMapUntil.removeCache("cacheEquiMap_2021");
            ConcurrentHashMapUntil.initDeviceCache("cacheEquiMap_2021",equipmen_list);
            ConcurrentHashMapUntil.initDeviceSizeCache("cacheEquiMap_2021",equipmenlist.size());
        }
        List<Qdsxj> list_new  = getDeviceDateList(list_qdsxj,equipmen_list,sb_name,sb_type,sb_ywdw);
        System.err.println("list_new="+list_new.size());
        if(list_new.size()>list_qdsxj.size()){
            ConcurrentHashMapUntil.removeCache("cacheMap_2021");
            ConcurrentHashMapUntil.initDeviceCache("cacheMap_2021",list_new);
        }
        return list_new;
    }

    private List<Qdsxj> getDeviceDateList(List<Qdsxj> list_qdsxj, List<Equipmen> equipmen_list, String sb_name, String sb_type, String sb_ywdw) {
        List<Qdsxj> list =new ArrayList<>();
        if(Strings.isNotBlank(sb_name) && Strings.isNotBlank(sb_type) && Strings.isNotBlank(sb_ywdw)){
            Pattern pattern = Pattern.compile(sb_name);
            for(int i=0;i<list_qdsxj.size();i++){
                Qdsxj qdsxj = list_qdsxj.get(i);
                Matcher matcher = pattern.matcher(list_qdsxj.get(i).getSb_name());
                if(list_qdsxj.get(i).getSb_devicePtzType() != null){
                    if(matcher.find() && sb_type.equals(list_qdsxj.get(i).getSb_devicePtzType()) && sb_ywdw.equals(list_qdsxj.get(i).getSb_ywdw())){
                        list.add(qdsxj);
                    }
                }
            }
            if(list.size()==0){
                Qdsxj qdsxj1= qdsxjMapper.getQdsxjBySbNameOnly(sb_name,sb_type,sb_ywdw);
                if(Objects.nonNull(qdsxj1)){
                    list.add(qdsxj1);
                }
            }
        }else if(Strings.isNotBlank(sb_type) && Strings.isNotBlank(sb_ywdw)){
            for(int i=0;i<list_qdsxj.size();i++){
                Qdsxj qdsxj = list_qdsxj.get(i);
                if(list_qdsxj.get(i).getSb_devicePtzType() != null){
                    if(sb_type.equals(list_qdsxj.get(i).getSb_devicePtzType()) && sb_ywdw.equals(list_qdsxj.get(i).getSb_ywdw())){
                        list.add(qdsxj);
                    }
                }
            }
            if(list.size()==0){
                List<Qdsxj> qdsxj1= qdsxjMapper.getQdsxjBySbTypeOnly(sb_type,sb_ywdw);
                if(!CollectionUtils.isEmpty(qdsxj1)){
                    list=qdsxj1;
                }
            }
        }else if(Strings.isNotBlank(sb_name) && Strings.isNotBlank(sb_ywdw)){
            Pattern pattern = Pattern.compile(sb_name);
            for(int i=0;i<list_qdsxj.size();i++){
                Qdsxj qdsxj = list_qdsxj.get(i);
                Matcher matcher = pattern.matcher(list_qdsxj.get(i).getSb_name());
                if(list_qdsxj.get(i).getSb_devicePtzType() != null){
                    if(matcher.find() && sb_ywdw.equals(list_qdsxj.get(i).getSb_ywdw())){
                        list.add(qdsxj);
                    }
                }
            }
            if(list.size()==0){
                Qdsxj qdsxj1= qdsxjMapper.getQdsxjBySbNameOnly(sb_name,sb_ywdw,null);
                if(Objects.nonNull(qdsxj1)){
                    list.add(qdsxj1);
                }
            }
        }else if(Strings.isNotBlank(sb_name) && Strings.isNotBlank(sb_type)){
            Pattern pattern = Pattern.compile(sb_name);
            for(int i=0;i<list_qdsxj.size();i++){
                Qdsxj qdsxj = list_qdsxj.get(i);
                Matcher matcher = pattern.matcher(list_qdsxj.get(i).getSb_name());
                if(list_qdsxj.get(i).getSb_devicePtzType() != null){
                    if(matcher.find() && sb_type.equals(list_qdsxj.get(i).getSb_devicePtzType())){
                        list.add(qdsxj);
                    }
                }
            }
            if(list.size()==0){
                Qdsxj qdsxj1= qdsxjMapper.getQdsxjBySbNameOnly(sb_name,null,sb_type);
                if(Objects.nonNull(qdsxj1)){
                    list.add(qdsxj1);
                }
            }
        }else if(Strings.isNotBlank(sb_name)){
            Pattern pattern = Pattern.compile(sb_name);
            for(int i=0;i<list_qdsxj.size();i++){
                Qdsxj qdsxj = list_qdsxj.get(i);
                Matcher matcher = pattern.matcher(list_qdsxj.get(i).getSb_name());
                if(matcher.find()){
                    list.add(qdsxj);
                }
            }
            if(list.size()==0){
                Qdsxj qdsxj1= qdsxjMapper.getQdsxjBySbNameOnly(sb_name,null,null);
                if(Objects.nonNull(qdsxj1)){
                    list.add(qdsxj1);
                }
            }
        }else if(Strings.isNotBlank(sb_type)){
            for(int i=0;i<list_qdsxj.size();i++){
                Qdsxj qdsxj = list_qdsxj.get(i);
                if(sb_type.equals(list_qdsxj.get(i).getSb_devicePtzType())){
                    list.add(qdsxj);
                }
            }
            if(list.size()==0){
                System.err.println("type");
                List<Qdsxj> qdsxj1= qdsxjMapper.getQdsxjBySbTypeOnly(sb_type,null);
                if(!CollectionUtils.isEmpty(qdsxj1)){
                    list=qdsxj1;
                }
            }
        }else if(Strings.isNotBlank(sb_ywdw)){
            for(int i=0;i<list_qdsxj.size();i++){
                Qdsxj qdsxj = list_qdsxj.get(i);
                if(sb_ywdw.equals(list_qdsxj.get(i).getSb_ywdw())){
                    list.add(qdsxj);
                }
            }
            if(list.size()==0){
                System.err.println("sb_ywdw");
                List<Qdsxj> qdsxj1= qdsxjMapper.getQdsxjBySbTypeOnly(null,sb_ywdw);
                if(!CollectionUtils.isEmpty(qdsxj1)){
                    list=qdsxj1;
                }
            }
        }

        for(Qdsxj qdsxj:list){
            for(Equipmen equipmen: equipmen_list){
                if(qdsxj.getSb_id().equals(equipmen.getSb_id())){
                    qdsxj.setChecked(true);
                }
            }
        }

        return list;
    }

    @Override
    public int updatedeviclanlog(Integer sb_id, Double correct_latitude, Double correct_longitude) {
        return qdsxjMapper.updatedeviclanlog(sb_id,correct_latitude,correct_longitude);
    }

    /**
     *设备在线率
     * @return
     */
    @Override
    public int getOnlineRate() {
        return qdsxjMapper.getOnlineRate();
    }

    @Override
    public Qdsxj getTaskByDev_code(String dev_code) {
        return qdsxjMapper.getTaskByDev_code(dev_code);
    }

    @Override
    public String caculateOnlinePercent() {
        int allEquipsCount = qdsxjMapper.getSbCount();
        List<OpWork> opWorkList = opWorkMapper.getByFaultType("设备离线");
        if(allEquipsCount == 0) {
            return "0.00%";
        }
        if(CollectionUtils.isEmpty(opWorkList)) {
            return "100.00";
        }
        int onlineCount = allEquipsCount- opWorkList.size();

        DecimalFormat df =new DecimalFormat();
        df.setMaximumFractionDigits(2);
        df.setMinimumFractionDigits(2);

        String percent = df.format(onlineCount *100.00 / allEquipsCount) +"%";
        return percent;

    }

    @Override
    public double getPerfactRate() {
        return qdsxjMapper.getPerfactRate();
    }

    @Override
    public List<Qdsxj> getQdsxYwdw() {
        return qdsxjMapper.getQdsxYwdw();
    }

    @Override
    public List<Qdsxj> getListByGwId(Integer gw_id) {
        List<Qdsxj> qdsxjs = qdsxjMapper.getListByGwId(gw_id);
        return qdsxjs;
    }

}
